/*
 * Stamina.cpp
 *
 *  Created on: 2014. 1. 23.
 *      Author: mega
 */

#include "../User.h"
#include "../NResource/Static.h"

#include "Stamina.h"

namespace ProjectZ { namespace NLogic {

Stamina::Stamina(User * pUser)
{
	_user			= pUser;
}

Stamina::~Stamina()
{

}

void
Stamina::Initialize()
{

}

void
Stamina::Finalize()
{

}

int
Stamina::GetCurrentKey()
{
	return _user->GetCharacterInfo().event_stamina;
}

bool
Stamina::IsKeyLack(int value)
{
	/*
	 * 이벤트 던전 & 월드보스 열쇠 부족 여부 확인
	 */
	int staminaGap = _user->GetCharacterInfo().event_stamina - value;
	if (staminaGap >= 0)
		return false;

	return true;
}

bool
Stamina::DecreaseKey(int value)
{
	/*
	 * 이벤트 던전 & 월드보스 열쇠 차감
	 */
	int maxStamina = NResource::Static::InstancePtr()->GetStaminaResource()->GetMaxStamina(_user);
	if (-1 == maxStamina)
	{
		DEBUGLOG("%s : maxStamina lookup fail.", __FUNCTION__);
		return false;
	}

	if (_user->GetCharacterInfo().event_stamina >= maxStamina)
		_user->GetCharacterInfo().recover_stamina_sec = time(NULL);

	_user->GetCharacterInfo().event_stamina -= value;
	return true;
}

bool
Stamina::InitializeEventDungeonKey()
{
	/*
	 * 이벤트던전 열쇠 초기화
	 */
	if (true == NResource::Static::InstancePtr()->GetEventTime()->IsWorldBossEvent(_user))
		return false;

	if (false == NResource::Static::InstancePtr()->GetEventTime()->IsOpenEventDungeon(_user))
	{
		_user->GetCharacterInfo().event_stamina = -1;
		return true;
	}

//	NResource::EventTimeData::Key clsKey(NResource::EventTimeResource::EventType::EM_EVENT_TYPE_EVENT_DUNGEON_OPEN, 0);
//	NResource::EventTimeData::Flyweight * pFly = NResource::Static::InstancePtr()->GetEventTime()->GetFly(_user, clsKey);

	int eventType = static_cast<int>(NResource::EventTimeResource::EventType::EM_EVENT_TYPE_EVENT_DUNGEON_OPEN);
	NResource::EventTimeData::Flyweight * pFly = NResource::Static::InstancePtr()->GetEventTime()->GetFly(_user, eventType);
	if (NULL == pFly)
	{
		DEBUGLOG("%s : pFly is NULL!!", __FUNCTION__);
		return false;
	}

	if (pFly->_START_SEC > static_cast<time_t>(_user->GetCharacterInfo().recover_stamina_sec))
	{
		_user->GetCharacterInfo().event_stamina = -1;
	}

	return true;
}

bool
Stamina::InitializeWorldBossDungeonKey()
{
	/*
	 * 월드보스던전 열쇠 초기화
	 */
	if (true == NResource::Static::InstancePtr()->GetEventTime()->IsOpenEventDungeon(_user))
		return false;

	if (false == NResource::Static::InstancePtr()->GetEventTime()->IsWorldBossEvent(_user))
	{
		_user->GetCharacterInfo().event_stamina = -1;
		return true;
	}

//	NResource::EventTimeData::Key clsKey(NResource::EventTimeResource::EventType::EM_EVENT_TYPE_WORLDBOSS_EVENT, 0);
//	NResource::EventTimeData::Flyweight * pFly = NResource::Static::InstancePtr()->GetEventTime()->GetFly(_user, clsKey);

	int eventType = static_cast<int>(NResource::EventTimeResource::EventType::EM_EVENT_TYPE_WORLDBOSS_EVENT);
	NResource::EventTimeData::Flyweight * pFly = NResource::Static::InstancePtr()->GetEventTime()->GetFly(_user, eventType);
	if (NULL == pFly)
	{
		DEBUGLOG("%s : pFly is NULL!!", __FUNCTION__);
		return false;
	}

	if (pFly->_START_SEC > static_cast<time_t>(_user->GetCharacterInfo().recover_stamina_sec))
	{
		_user->GetCharacterInfo().event_stamina = -1;
	}

	return true;
}

int64_t
Stamina::UpdateKeyRecoveryTime()
{
	/*
	 * 이벤트 던전 & 월드보스 열쇠 복구 시간 갱신
	 */
	int maxStamina = NResource::Static::InstancePtr()->GetStaminaResource()->GetMaxStamina(_user);
	if (-1 == maxStamina)
	{
		DEBUGLOG("%s : maxStamina lookup fail.", __FUNCTION__);
		return 0;
	}

	int recoveryMinute = NResource::Static::InstancePtr()->GetStaminaResource()->GetRecoveryMinute(_user);
	if (-1 == recoveryMinute)
	{
		DEBUGLOG("%s : recoveryMinute lookup fail.", __FUNCTION__);
		return 0;
	}

	int recoverySec = recoveryMinute * 60;

	// 이벤트에 최초로 참여하거나 현재 열쇠가 최대인 경우
	if (_user->GetCharacterInfo().event_stamina	== -1 || _user->GetCharacterInfo().event_stamina >= maxStamina)
	{
		_user->GetCharacterInfo().event_stamina = maxStamina;
		_user->GetCharacterInfo().recover_stamina_sec = time(NULL);
		return 0;
	}

	time_t currentSec = time(NULL);

	// 현재 시간 기준 지난 시간 계산
	int elapsedSec = currentSec - _user->GetCharacterInfo().recover_stamina_sec;

	// 회복 할 열쇠 계산
	int recoveryStamina = elapsedSec / recoverySec;

	DEBUGLOG("%s : user_seq=%d, slot_seq=%d, elapsed_sec=%d, recover_stamina=%d", __FUNCTION__,
			_user->GetUserSeq(), _user->GetCharacterInfo().characterseq, elapsedSec, recoveryStamina);

	int64_t remainSec = 0;

	if (recoveryStamina <= 0)
	{
		// 열쇠 회복 시간이 지나지 않은 경우
		remainSec = recoverySec - elapsedSec;
	}
	else
	{
		// 열쇠 회복 시간이 지난 경우
		_user->GetCharacterInfo().event_stamina += recoveryStamina;

		if (_user->GetCharacterInfo().event_stamina >= maxStamina)
		{
			remainSec = 0;
			_user->GetCharacterInfo().event_stamina = maxStamina;
			_user->GetCharacterInfo().recover_stamina_sec = currentSec;
		}
		else
		{
			// 열쇠가 최대가 아니면 남은 시간을 누적한다.
			remainSec = recoverySec - (elapsedSec % recoverySec);
			_user->GetCharacterInfo().recover_stamina_sec += (recoverySec * recoveryStamina);
		}
	}

	return remainSec;
}


int
Stamina::UpdateStaminaRecoveryTime()
{
	/*
	 * 던전 체력치 복구 시간 갱신
	 */
	// 현재 체력치가 기본 체력치의 최대값보다 큰 경우 충전 시간을 계산하지 않는다
	if (_user->GetCharacterInfo().cur_stamina >= static_cast<uint32_t>(STAMINA_MAX))
	{
		_user->GetCharacterInfo().reserve2 = time(NULL);
		return 0;
	}

	time_t currentSec = time(NULL);

	// 현재 시간 기준 지난 시간 계산
	int elapsedSec = currentSec - _user->GetCharacterInfo().reserve2;

	if (elapsedSec < 0)
	{
		elapsedSec = 0;
	}

	// 회복 할 스태미너 계산
	int recoveryStamina = elapsedSec / STAMINA_RECOVERY_SEC;

	int remainSec = 0;

	if (recoveryStamina <= 0)
	{
		// 스태미너 회복 시간이 지나지 않은 경우
		remainSec = STAMINA_RECOVERY_SEC - elapsedSec;
	}
	else
	{
		// 스태미너 회복 시간이 지난 경우
		_user->GetCharacterInfo().cur_stamina += recoveryStamina;

		if (_user->GetCharacterInfo().cur_stamina >= static_cast<uint32_t>(STAMINA_MAX))
		{
			remainSec = 0;
			_user->GetCharacterInfo().cur_stamina = STAMINA_MAX;
			_user->GetCharacterInfo().reserve2 = currentSec;
		}
		else
		{
			// 스태미너가 최대가 아니면 남은 시간을 누적한다.
			remainSec = STAMINA_RECOVERY_SEC - (elapsedSec % STAMINA_RECOVERY_SEC);
			_user->GetCharacterInfo().reserve2 += (STAMINA_RECOVERY_SEC * recoveryStamina);
		}
	}

	return remainSec;
}

bool
Stamina::IsStaminaLack(int mode)
{
	/*
	 * 체력치 부족 여부 확인
	 */
	int needStamina = this->GetDungeonStamina(mode);

	int staminaGap = _user->GetCharacterInfo().cur_stamina - needStamina;
	if (staminaGap >= 0)
		return false;

	return true;
}

bool
Stamina::DecreaseStamina(int mode)
{
	/*
	 * 체력치 차감
	 */
	int subStamina = this->GetDungeonStamina(mode);

	if (_user->GetCharacterInfo().cur_stamina >= static_cast<unsigned int>(STAMINA_MAX))
	{
		_user->GetCharacterInfo().reserve2 = time(NULL);
	}

	_user->GetCharacterInfo().cur_stamina -= subStamina;

	if (0 > _user->GetCharacterInfo().cur_stamina)
	{
		_user->GetCharacterInfo().cur_stamina = 0;
	}

	return true;
}

int
Stamina::GetDungeonStamina(int mode)
{
	/*
	 * 던전 모드별 차감 체력치
	 * 노멀: 8, 하드: 10, 헬: 12
	 */
	int stamina = 12;

	switch (mode)
	{
	case 0: stamina = 8; break;
	case 1: stamina = 10; break;
	case 2: stamina = 12; break;
	}

	return stamina;
}

} /*NLogic*/ } /* namespace ProjectZ */
